#include "ShopRoom.hh"
#include <iostream>
#include <algorithm>
#include <ctime>
#include "IO.hh"

ShopRoom::ShopRoom(const std::string& name, const std::string& text)
    : Room(name, text), rng(static_cast<unsigned>(std::time(nullptr))) {
    shopItems = generateShopItems();
}

std::vector<Item> ShopRoom::generateShopItems() {
    const auto& allItems = getAllShopItems(); //const auto的作用是避免复制整个函数，提高效率 //The purpose of const auto is to avoid duplicating the entire function, making it more efficient
    std::vector<Item> weapons, armors, potions, result; // 建了四个空的向量，其中第四个存放最终选中的三个物品 Four empty vectors were built, with the fourth holding the final three items

    for (const auto& item : allItems) {
        if (soldItemNames.count(item.name)) continue; //判断当前物品是否被卖了出去 //Determines if the current item has been sold
        switch (item.type) {
            case Item::Type::Weapon: weapons.push_back(item); break; //如果是武器则将加入武器向量里 //If it's a weapon, it will be added to the weapon vector
            case Item::Type::Armor: armors.push_back(item); break;
            case Item::Type::HealPotion:
            case Item::Type::DefencePotion:
            case Item::Type::BoostPotion: potions.push_back(item); break;
            default: break;
        }
    }

    //如果还有武器没卖出，则随机抽一个放到result里 
    //If there are still weapons that have not been sold, one will be randomly selected and placed in the result
    if (!weapons.empty()) result.push_back(weapons[std::uniform_int_distribution<>(0, weapons.size() - 1)(rng)]); 
    if (!armors.empty()) result.push_back(armors[std::uniform_int_distribution<>(0, armors.size() - 1)(rng)]);
    if (!potions.empty()) result.push_back(potions[std::uniform_int_distribution<>(0, potions.size() - 1)(rng)]);
    return result;
}

void ShopRoom::showShopItems() const {
    std::cout << "\n--- Shop Inventory ---\n";
    for (size_t i = 0; i < shopItems.size(); i++) {
        std::cout << i + 1 << ". ";
        if (soldItemNames.count(shopItems[i].name)) std::cout << "[Sold Out]"; //判断现在售卖的商品名字是否在已经卖出的商品名单里 //Determine whether the name of the product currently sold is in the list of products that have already been sold
        else std::cout << shopItems[i].name << " [" << shopItems[i].type << "] - "
                       << shopItems[i].description << " | Price: " << shopItems[i].value << " golds";
        std::cout << "\n";
    }
    std::cout << "-----------------------\n";
}

void ShopRoom::printPlayerEquipment(const Player& player) const {
    std::cout << "Your current equipments:\n --Weapon: ";
    //auto*是让编译器自动推导w的类型，并且这是一个指针，判断是否装备武器
    //auto* is the type that the compiler automatically derives w, and this is a pointer to determine whether a weapon is equipped
    if (auto* w = player.getEquippedWeapon()) 
        std::cout << w->name << " (+" << w->value << " ATK, Level " << w->level << ")\n";
    else std::cout << "No equipped weapon.\n";

    std::cout << " --Armor: ";
    if (auto* a = player.getEquippedArmor())
        std::cout << a->name << " (+" << a->value << " DEF, Level " << a->level << ")\n";
    else std::cout << "No equipped armor.\n";
}

void ShopRoom::enterRoom(Player& player) {
    std::cout << "\nYou have entered the shop: " << getName() << "\n";
    shopItems = generateShopItems();
    showShopItems();

    bool shopping = true;
    while (shopping) {
        std::cout << "\nYour gold: " << player.getGold() 
                  << ", Action Points: " << player.getAP() << "\n";
        printPlayerEquipment(player);
        std::cout << "[1] Buy Item\n[2] Refresh Shop (-1 AP)\n[3] See all shop item\n[4] View Player Status\n[5] Leave\nChoose: ";

        switch (IO::getNumber()) {
            case 1: {
                std::cout << "Enter the item number you want to buy: ";
                int idx = IO::getNumber(); //
                if (idx < 1 || idx > (int)shopItems.size()) {
                    std::cout << "Invalid selection.\n"; break;
                }
                const auto& item = shopItems[idx - 1]; //根据玩家要买的物品的下标获取对应的商品 //Obtain the corresponding product according to the subscript of the item to be bought
                if (soldItemNames.count(item.name)) {
                    std::cout << "Sorry, this item is already sold out.\n"; break;
                }
                if (player.getGold() < item.value) {
                    std::cout << "You don't have enough golds.\n"; break;
                }
                player.spendGold(item.value);
                if (item.type == Item::Type::Weapon || item.type == Item::Type::Armor)
                    player.equipItem(item);
                else {
                    player.addItem(item);
                    std::cout << "You added " << item.name << " to your inventory.\n";
                }
                soldItemNames.insert(item.name); //把卖出的商品标记 //Mark the sold item
                break;
            }
            case 2: refreshShop(player); break;
            case 3: showShopItems(); break;
            case 4: player.displayStatus(); break;
            case 5: std::cout << "You have left the shop.\n"; shopping = false; break;
            default: std::cout << "Invalid input.\n"; break;
        }
    }
}

void ShopRoom::refreshShop(Player& player) {
    if (player.getAP() <= 0) {
        std::cout << "You don't have enough action points.\n";
        return;
    }
    player.useAP(); 
    shopItems = generateShopItems(); // 重新刷新商店 //Refresh the shop
    std::cout << "\nShop inventory has been refreshed!\n";
    showShopItems();
}
